package org.jeecg.config;

import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.jeecg.modules.shiro.authc.ShiroRealm;
import org.jeecg.modules.shiro.authc.aop.JwtFilter;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author: Scott
 * @date: 2018/2/7
 * @description: shiro 配置类
 */

@Configuration
public class ShiroConfig {
	
	/**
	 * Filter Chain定义说明 
	 * 
	 * 1、一个URL可以配置多个Filter，使用逗号分隔
	 * 2、当设置多个过滤器时，全部验证通过，才视为通过
	 * 3、部分过滤器可指定参数，如perms，roles
	 */
	@Bean("shiroFilter")
	public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		// 拦截器
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		// 配置不会被拦截的链接 顺序判断
		filterChainDefinitionMap.put("/b/api/**", "anon");
		filterChainDefinitionMap.put("/b/sys/loginfo", "anon"); //测试
		filterChainDefinitionMap.put("/b/sys/app/login", "anon"); //app登录
		filterChainDefinitionMap.put("/b/sys/login", "anon"); //登录接口排除
		filterChainDefinitionMap.put("/b/sys/upload/**", "anon"); //图片上传接口
        filterChainDefinitionMap.put("/b/sys/appWebBtn/**", "anon"); //图片按钮
        filterChainDefinitionMap.put("/b/sys/sysAppVersion/getNewVersion", "anon"); //app版本获取接口
	    //filterChainDefinitionMap.put("/b/app/sys/appBtn/queryAppButtonList", "anon"); //web按钮控制
		filterChainDefinitionMap.put("/b/meter/foreign/**", "anon"); //水电表
		filterChainDefinitionMap.put("/b/foreign/**", "anon"); //车禁
		filterChainDefinitionMap.put("/b/sys/logout", "logout"); //退出登录接口
		filterChainDefinitionMap.put("/b/sys/getEncryptedString", "anon"); //获取加密串
		filterChainDefinitionMap.put("/b/station/app/list", "anon"); //APP登录接口排除
		filterChainDefinitionMap.put("/b/sys/sms", "anon");//短信验证码
		filterChainDefinitionMap.put("/b/meterOrder/foreign/**", "anon");//水电表支付
		filterChainDefinitionMap.put("/b/sys/phoneLogin", "anon");//手机登录
		filterChainDefinitionMap.put("/b/sys/user/checkOnlyUser", "anon");//校验用户是否存在
		filterChainDefinitionMap.put("/b/sys/user/register", "anon");//用户注册
		filterChainDefinitionMap.put("/b/sys/user/querySysUser", "anon");//根据手机号获取用户信息
		filterChainDefinitionMap.put("/b/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号
		filterChainDefinitionMap.put("/b/sys/user/passwordChange", "anon");//用户更改密码
		filterChainDefinitionMap.put("/b/auth/2step-code", "anon");//登录验证码
		filterChainDefinitionMap.put("/b/sys/common/view/**", "anon");//图片预览不限制token
		filterChainDefinitionMap.put("/b/sys/common/download/**", "anon");//文件下载不限制token
		filterChainDefinitionMap.put("/b/sys/common/pdf/**", "anon");//pdf预览
		filterChainDefinitionMap.put("/b/generic/**", "anon");//pdf预览需要文件
		filterChainDefinitionMap.put("/b/", "anon");
		filterChainDefinitionMap.put("/b/doc.html", "anon");
		filterChainDefinitionMap.put("/b/**/*.js", "anon");
		filterChainDefinitionMap.put("/b/**/*.css", "anon");
		filterChainDefinitionMap.put("/b/**/*.html", "anon");
		filterChainDefinitionMap.put("/b/**/*.svg", "anon");
		filterChainDefinitionMap.put("/b/**/*.jpg", "anon");
		filterChainDefinitionMap.put("/b/**/*.png", "anon");
		filterChainDefinitionMap.put("/b/**/*.ico", "anon");
		filterChainDefinitionMap.put("/b/druid/**", "anon");
		filterChainDefinitionMap.put("/b/swagger-ui.html", "anon");
		filterChainDefinitionMap.put("/b/swagger**/**", "anon");
		filterChainDefinitionMap.put("/b/webjars/**", "anon");
		filterChainDefinitionMap.put("/b/v2/**", "anon");
		filterChainDefinitionMap.put("/b/charge/appIntoPay", "anon");//支付
		filterChainDefinitionMap.put("/b/charge/*", "anon");//支付
		filterChainDefinitionMap.put("/b/charge/app/*", "anon");//收费APP接口
		filterChainDefinitionMap.put("/b/charge/makeinvoice/*", "anon");//开票APP接口
		filterChainDefinitionMap.put("/b/charge/makeInvoiceYy/*", "anon");//开票APP接口
		filterChainDefinitionMap.put("/b/charge/makeInvoiceGx/*", "anon");//开票APP接口
		filterChainDefinitionMap.put("/b/car/app/*", "anon");//车辆开卡缴费
		filterChainDefinitionMap.put("/b/app/wx/**", "anon");//小程序接口
		filterChainDefinitionMap.put("/b/charge/app/wxpay/wxIntoPay", "anon");//小程序支付
		filterChainDefinitionMap.put("/b/charge/app/wxpay/notify_demo", "anon");//小程序回调
		//性能监控
		filterChainDefinitionMap.put("/b/actuator/metrics/**", "anon");
		filterChainDefinitionMap.put("/b/actuator/httptrace/**", "anon");
		filterChainDefinitionMap.put("/b/actuator/redis/**", "anon");
		filterChainDefinitionMap.put("/b/sys/user/initUserRolePermission", "anon");

		filterChainDefinitionMap.put("/b/engineering/equipInfo/collectData", "anon");
		filterChainDefinitionMap.put("/b/sys/sysAppVersion/getAppVersionURL", "anon");
		
		// 添加自己的过滤器并且取名为jwt
		Map<String, Filter> filterMap = shiroFilterFactoryBean.getFilters();
		filterMap.put("authc", new JwtFilter());
		// <!-- 过滤链定义，从上向下顺序执行，一般将/**放在最为下边
		filterChainDefinitionMap.put("/b/**", "authc");

		// 未授权界面返回JSON
		shiroFilterFactoryBean.setUnauthorizedUrl("/b/sys/common/403");
		shiroFilterFactoryBean.setLoginUrl("/b/sys/common/403");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}

	@Bean("securityManager")
	public DefaultWebSecurityManager securityManager(ShiroRealm myRealm) {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(myRealm);

		/*
		 * 关闭shiro自带的session，详情见文档
		 * http://shiro.apache.org/session-management.html#SessionManagement-
		 * StatelessApplications%28Sessionless%29
		 */
		DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
		DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
		defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
		subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
		securityManager.setSubjectDAO(subjectDAO);

		return securityManager;
	}


	/**
	 * 下面的代码是添加注解支持
	 * @return
	 */
	@Bean
	@DependsOn("lifecycleBeanPostProcessor")
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
		defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
		return defaultAdvisorAutoProxyCreator;
	}

	@Bean
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}

	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
		advisor.setSecurityManager(securityManager);
		return advisor;
	}

}
